
package com.tenentia.pcmps.swm.data.implementation;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;

import com.tenentia.pcmps.swm.Constants;
import com.tenentia.pcmps.swm.data.DataAccessException;
import com.tenentia.pcmps.swm.data.beans.ApplicationUser;
import com.tenentia.pcmps.swm.data.beans.UsersGroup;
import com.tenentia.pcmps.swm.data.interfaces.GroupsDAO;
import com.tenentia.pcmps.swm.data.util.IBatisUtilities;

public class GroupsDAOImpl implements GroupsDAO {

	private static final Logger LOGGER = Logger.getLogger(GroupsDAOImpl.class.getPackage().getName());

	GroupsDAOImpl() {

		super();
	}

	@Override
	public void delete(UsersGroup group) throws DataAccessException {

		LOGGER.debug(Constants.STRING_L4J_METHOD_BEGIN);

		Exception catchedException = null;

		int tmpInt = 0;

		try {
			IBatisUtilities.getSqlMapClient().startTransaction();
			tmpInt = IBatisUtilities.getSqlMapClient().delete("deleteGroupMembers", group.getInternalID());
			LOGGER.debug(tmpInt);
			tmpInt = IBatisUtilities.getSqlMapClient().delete("deleteGroup", group.getInternalID());
			LOGGER.debug(tmpInt);
			IBatisUtilities.getSqlMapClient().commitTransaction();
		} catch (Exception e) {
			LOGGER.error(e, e);
			catchedException = e;
		} finally {
			try {
				IBatisUtilities.getSqlMapClient().endTransaction();
			} catch (Exception e) {
				LOGGER.error(e, e);
			}
		}

		if (null != catchedException) {
			throw new DataAccessException(catchedException);
		}
	}

	@Override
	public UsersGroup get(UsersGroup group) throws DataAccessException {

		LOGGER.debug(Constants.STRING_L4J_METHOD_BEGIN);

		UsersGroup methodResult;

		try {
			methodResult = (UsersGroup) IBatisUtilities.getSqlMapClient().queryForObject("getGroup", group);

			List<?> tmpList = IBatisUtilities.getSqlMapClient().queryForList("getGroupMembersByGroupID", methodResult.getInternalID());

			if (null != tmpList && tmpList.size() > 0) {

				Set<ApplicationUser> members = new HashSet<ApplicationUser>();

				for (Iterator<?> iterator = tmpList.iterator(); iterator.hasNext();) {
					Long tmpUserID = (Long) iterator.next();
					ApplicationUser tmpApplicationUser = new ApplicationUser();
					tmpApplicationUser.setInternalID(tmpUserID);
					members.add(tmpApplicationUser);
				}

				methodResult.setMembers(members);
			}
			LOGGER.debug("methodResult: " + methodResult);
		} catch (Exception e) {
			LOGGER.error(e, e);
			throw new DataAccessException(e);
		}

		return methodResult;
	}
	
	@Override
	public List<UsersGroup> getAvailableGroups() throws DataAccessException {

		LOGGER.debug(Constants.STRING_L4J_METHOD_BEGIN);

		List<UsersGroup> methodResult;

		try {
			List<?> tmpList = IBatisUtilities.getSqlMapClient().queryForList("getGroupsItemsByRange");

			if (null == tmpList || tmpList.size() == 0) {
				LOGGER.debug("No results...");
				methodResult = new ArrayList<UsersGroup>();
			} else {
				methodResult = new ArrayList<UsersGroup>();
				for (int i = 0; i < tmpList.size(); i++) {
					UsersGroup tmpInstance = (UsersGroup) tmpList.get(i);
					methodResult.add(tmpInstance);
					LOGGER.debug("tmpInstance: " + tmpInstance);
				}
			}
		} catch (Exception e) {
			LOGGER.error(e, e);
			throw new DataAccessException(e);
		}

		return methodResult;
	}

	@Override
	public List<UsersGroup> getTableItemsByRange(Object filterParameters, Object sortParameters, Integer firstRow, Integer numberOfRows) throws DataAccessException {

		LOGGER.debug(Constants.STRING_L4J_METHOD_BEGIN);

		LOGGER.debug("firstRow: " + firstRow.intValue());
		LOGGER.debug("numberOfRows: " + numberOfRows.intValue());

		List<UsersGroup> methodResult;

		try {
			List<?> tmpList = IBatisUtilities.getSqlMapClient().queryForList("getGroupsItemsByRange", firstRow, numberOfRows);

			if (null == tmpList || tmpList.size() == 0) {
				LOGGER.debug("No results...");
				methodResult = new ArrayList<UsersGroup>();
			} else {
				methodResult = new ArrayList<UsersGroup>();
				for (int i = 0; i < tmpList.size(); i++) {
					UsersGroup tmpInstance = (UsersGroup) tmpList.get(i);
					methodResult.add(tmpInstance);
					LOGGER.debug("tmpInstance: " + tmpInstance);
				}
			}
		} catch (Exception e) {
			LOGGER.error(e, e);
			throw new DataAccessException(e);
		}

		return methodResult;
	}

	@Override
	public Integer getTableRowCount(Object filterParameters) throws DataAccessException {

		LOGGER.debug(Constants.STRING_L4J_METHOD_BEGIN);

		Integer methodResult;

		try {
			methodResult = (Integer) IBatisUtilities.getSqlMapClient().queryForObject("getGroupsRowCount");
			LOGGER.debug("methodResult: " + methodResult.intValue());
		} catch (Exception e) {
			LOGGER.error(e, e);
			throw new DataAccessException(e);
		}

		return methodResult;
	}

	public UsersGroup getUserGroup(ApplicationUser user) throws DataAccessException {

		LOGGER.debug(Constants.STRING_L4J_METHOD_BEGIN);

		UsersGroup methodResult;

		try {
			methodResult = (UsersGroup) IBatisUtilities.getSqlMapClient().queryForObject("getUserGroup", user.getInternalID());
		} catch (Exception e) {
			LOGGER.error(e, e);
			throw new DataAccessException(e);
		}

		return methodResult;
	}

	@Override
	public UsersGroup save(UsersGroup group) throws DataAccessException {

		LOGGER.debug(Constants.STRING_L4J_METHOD_BEGIN);

		UsersGroup methodResult = null;

		Exception catchedException = null;

		try {
			IBatisUtilities.getSqlMapClient().startTransaction();
			Long groupID = (Long) IBatisUtilities.getSqlMapClient().insert("insertGroup", group);
			group.setInternalID(groupID);
			if (null != group.getMembers() && group.getMembers().size() > 0) {
				for (Iterator<ApplicationUser> iterator = group.getMembers().iterator(); iterator.hasNext();) {
					ApplicationUser tmpApplicationUser = iterator.next();
					UsersGroup tmpUsersGroup = new UsersGroup();
					tmpUsersGroup.setInternalID(groupID);
					tmpApplicationUser.setGroup(tmpUsersGroup);
					IBatisUtilities.getSqlMapClient().insert("insertUserGroupRelation", tmpApplicationUser);
				}
			}
			IBatisUtilities.getSqlMapClient().commitTransaction();
			methodResult = get(group);
		} catch (Exception e) {
			LOGGER.error(e, e);
			catchedException = e;
		} finally {
			try {
				IBatisUtilities.getSqlMapClient().endTransaction();
			} catch (Exception e) {
				LOGGER.error(e, e);
			}
		}

		if (null != catchedException) {
			throw new DataAccessException(catchedException);
		}

		return methodResult;

	}

	@Override
	public UsersGroup setUserGroup(ApplicationUser user) throws DataAccessException {

		LOGGER.debug(Constants.STRING_L4J_METHOD_BEGIN);

		UsersGroup methodResult = null;

		Exception catchedException = null;

		try {
			IBatisUtilities.getSqlMapClient().startTransaction();
			try {
				IBatisUtilities.getSqlMapClient().insert("insertUserGroupRelation", user);
				IBatisUtilities.getSqlMapClient().commitTransaction();
			} catch (Exception e) {
				IBatisUtilities.getSqlMapClient().insert("updateUserGroupRelation", user);
				IBatisUtilities.getSqlMapClient().commitTransaction();
			}
			IBatisUtilities.getSqlMapClient().commitTransaction();
			methodResult = getUserGroup(user);
		} catch (Exception e) {
			LOGGER.error(e, e);
			catchedException = e;
		} finally {
			try {
				IBatisUtilities.getSqlMapClient().endTransaction();
			} catch (Exception e) {
				LOGGER.error(e, e);
			}
		}

		if (null != catchedException) {
			throw new DataAccessException(catchedException);
		}

		return methodResult;
	}

	@Override
	public UsersGroup update(UsersGroup group) throws DataAccessException {

		LOGGER.debug(Constants.STRING_L4J_METHOD_BEGIN);

		UsersGroup methodResult = null;

		Exception catchedException = null;

		int tmpInt = 0;

		try {
			IBatisUtilities.getSqlMapClient().startTransaction();
			tmpInt = IBatisUtilities.getSqlMapClient().update("updateGroup", group);
			LOGGER.debug(tmpInt);
			tmpInt = IBatisUtilities.getSqlMapClient().delete("deleteGroupMembers", group.getInternalID());
			LOGGER.debug(tmpInt);
			if (null != group.getMembers() && group.getMembers().size() > 0) {
				for (Iterator<ApplicationUser> iterator = group.getMembers().iterator(); iterator.hasNext();) {
					ApplicationUser tmpApplicationUser = iterator.next();
					UsersGroup tmpUsersGroup = new UsersGroup();
					tmpUsersGroup.setInternalID(group.getInternalID());
					tmpApplicationUser.setGroup(tmpUsersGroup);
					IBatisUtilities.getSqlMapClient().insert("insertUserGroupRelation", tmpApplicationUser);
				}
			}
			IBatisUtilities.getSqlMapClient().commitTransaction();
			methodResult = get(group);
		} catch (Exception e) {
			LOGGER.error(e, e);
			catchedException = e;
		} finally {
			try {
				IBatisUtilities.getSqlMapClient().endTransaction();
			} catch (Exception e) {
				LOGGER.error(e, e);
			}
		}

		if (null != catchedException) {
			throw new DataAccessException(catchedException);
		}

		return methodResult;
	}
}
